diff options
Diffstat (limited to 'src/core/hle/service/audio/audio_renderer.cpp')
-rw-r--r-- | src/core/hle/service/audio/audio_renderer.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/core/hle/service/audio/audio_renderer.cpp b/src/core/hle/service/audio/audio_renderer.cpp new file mode 100644 index 000000000..68415eb8f --- /dev/null +++ b/src/core/hle/service/audio/audio_renderer.cpp @@ -0,0 +1,210 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/audio/audio_renderer.h" +#include "core/hle/service/ipc_helpers.h" + +namespace Service::Audio { +using namespace AudioCore::Renderer; + +IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, + AudioCore::AudioRendererParameterInternal& params, + Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, + u32 process_handle, Kernel::KProcess& process_, + u64 applet_resource_user_id, s32 session_id) + : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, + rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, + impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, + {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"}, + {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"}, + {3, &IAudioRenderer::GetState, "GetState"}, + {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"}, + {5, &IAudioRenderer::Start, "Start"}, + {6, &IAudioRenderer::Stop, "Stop"}, + {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"}, + {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, + {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, + {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"}, + {11, nullptr, "ExecuteAudioRendererRendering"}, + {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"}, + {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"}, + }; + // clang-format on + RegisterHandlers(functions); + + process.Open(); + impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process, + applet_resource_user_id, session_id); +} + +IAudioRenderer::~IAudioRenderer() { + impl->Finalize(); + service_context.CloseEvent(rendered_event); + process.Close(); +} + +void IAudioRenderer::GetSampleRate(HLERequestContext& ctx) { + const auto sample_rate{impl->GetSystem().GetSampleRate()}; + + LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(sample_rate); +} + +void IAudioRenderer::GetSampleCount(HLERequestContext& ctx) { + const auto sample_count{impl->GetSystem().GetSampleCount()}; + + LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(sample_count); +} + +void IAudioRenderer::GetState(HLERequestContext& ctx) { + const u32 state{!impl->GetSystem().IsActive()}; + + LOG_DEBUG(Service_Audio, "called, state {}", state); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(state); +} + +void IAudioRenderer::GetMixBufferCount(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + const auto buffer_count{impl->GetSystem().GetMixBufferCount()}; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(buffer_count); +} + +void IAudioRenderer::RequestUpdate(HLERequestContext& ctx) { + LOG_TRACE(Service_Audio, "called"); + + const auto input{ctx.ReadBuffer(0)}; + + // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for + // checking size 0. Performance size is 0 for most games. + + auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0}; + if (is_buffer_b) { + const auto buffersB{ctx.BufferDescriptorB()}; + output_buffer.resize_destructive(buffersB[0].Size()); + performance_buffer.resize_destructive(buffersB[1].Size()); + } else { + const auto buffersC{ctx.BufferDescriptorC()}; + output_buffer.resize_destructive(buffersC[0].Size()); + performance_buffer.resize_destructive(buffersC[1].Size()); + } + + auto result = impl->RequestUpdate(input, performance_buffer, output_buffer); + + if (result.IsSuccess()) { + if (is_buffer_b) { + ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0); + ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1); + } else { + ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0); + ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1); + } + } else { + LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription()); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + +void IAudioRenderer::Start(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + impl->Start(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IAudioRenderer::Stop(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + impl->Stop(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IAudioRenderer::QuerySystemEvent(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(Audio::ResultNotSupported); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(rendered_event->GetReadableEvent()); +} + +void IAudioRenderer::SetRenderingTimeLimit(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + IPC::RequestParser rp{ctx}; + auto limit = rp.PopRaw<u32>(); + + auto& system_ = impl->GetSystem(); + system_.SetRenderingTimeLimit(limit); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IAudioRenderer::GetRenderingTimeLimit(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + auto& system_ = impl->GetSystem(); + auto time = system_.GetRenderingTimeLimit(); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(time); +} + +void IAudioRenderer::ExecuteAudioRendererRendering(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); +} + +void IAudioRenderer::SetVoiceDropParameter(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + IPC::RequestParser rp{ctx}; + auto voice_drop_param{rp.Pop<f32>()}; + + auto& system_ = impl->GetSystem(); + system_.SetVoiceDropParameter(voice_drop_param); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IAudioRenderer::GetVoiceDropParameter(HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + auto& system_ = impl->GetSystem(); + auto voice_drop_param{system_.GetVoiceDropParameter()}; + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(voice_drop_param); +} + +} // namespace Service::Audio |